package com.yeebo.admin.domain;

import cn.hutool.core.bean.BeanUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.yeebo.admin.dao.SysResourceDao;
import com.yeebo.admin.dao.SysRoleDao;
import com.yeebo.admin.dao.SysRoleResourceDao;
import com.yeebo.enums.admin.ResourceLevelEnums;
import com.yeebo.model.admin.SysResource;
import com.yeebo.model.admin.SysRole;
import com.yeebo.model.admin.SysRoleResource;
import com.yeebo.vo.admin.SysResourcesTreeVO;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Component("sysRoleDomain")
public class SysRoleDomain {

    @Resource
    private SysRoleDao sysRoleDao;
    @Resource
    private SysResourceDao sysResourceDao;
    @Resource
    private SysRoleResourceDao sysRoleResourceDao;

    public Page<SysRole> loadSysRoleList(Integer pageNo, Integer pageSize, String filterRoleName) {
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("filterRoleName", filterRoleName);
        PageHelper.startPage(pageNo, pageSize);
        Page<SysRole> sysRolePage = sysRoleDao.loadSysRoleList(queryMap);
        return sysRolePage;
    }

    public SysRole getSysRoleByCode(String roleCode) {
        return sysRoleDao.getRoleByCode(roleCode);
    }

    public SysRole getSysRoleById(Long roleId) {
        return sysRoleDao.getRoleById(roleId);
    }

    public void updateSysRole(SysRole updateEntity) {
        sysRoleDao.update(updateEntity);
    }

    public void addSysRole(String roleCode, String roleName, String roleDesc) {
        Date now = new Date();
        SysRole addEntity = new SysRole();
        addEntity.setRoleCode(roleCode);
        addEntity.setRoleName(roleName);
        addEntity.setRoleDesc(roleDesc);
        addEntity.setValid(true);
        addEntity.setCreatedTime(now);
        addEntity.setUpdatedTime(now);
        sysRoleDao.add(addEntity);
    }

    public List<SysResourcesTreeVO> loadSysResourcesTree() {
        List<SysResource> allValidResources = sysResourceDao.loadAllValidResources();

        List<SysResource> firstLevelResources = allValidResources.stream().filter(s -> s.getResourceLevel().equals(ResourceLevelEnums.ONE.getLevel())).collect(Collectors.toList());
        List<SysResource> secondLevelResources = allValidResources.stream().filter(s -> s.getResourceLevel().equals(ResourceLevelEnums.TWO.getLevel())).collect(Collectors.toList());
        List<SysResource> thirdLevelResources = allValidResources.stream().filter(s -> s.getResourceLevel().equals(ResourceLevelEnums.THREE.getLevel())).collect(Collectors.toList());
        List<SysResourcesTreeVO> resultList = generateNeedResourceList(firstLevelResources, secondLevelResources, thirdLevelResources);

        return resultList;
    }

    public List<SysResource> loadCurrentHaveResourcesByRoleId(Long roleId) {
        return sysResourceDao.loadResourcesByRoleId(roleId);
    }

    public List<SysResourcesTreeVO> generateNeedResourceList(List<SysResource> firstLevelResources, List<SysResource> secondLevelResources,
                                                             List<SysResource> thirdLevelResources) {
        List<SysResourcesTreeVO> resultList = new LinkedList<>();

        for (SysResource parentResource : firstLevelResources) {
            SysResourcesTreeVO target = new SysResourcesTreeVO();
            BeanUtil.copyProperties(parentResource, target);
            target.setResourceId(parentResource.getId());

            if (ResourceLevelEnums.THREE.getLevel().equals(parentResource.getResourceLevel())) {
                target.setChildrenList(null);
            } else if (ResourceLevelEnums.TWO.getLevel().equals(parentResource.getResourceLevel())) {
                List<SysResource> currentMatchChildResources = secondLevelResources.stream().filter(s -> s.getParentMenuId().equals(parentResource.getId())).collect(Collectors.toList());
                target.setChildrenList(generateNeedResourceList(currentMatchChildResources, new LinkedList<>(), new LinkedList<>()));
            } else if (ResourceLevelEnums.ONE.getLevel().equals(parentResource.getResourceLevel())) {
                List<SysResource> currentMatchChildResources = secondLevelResources.stream().filter(s -> s.getParentMenuId().equals(parentResource.getId())).collect(Collectors.toList());
                target.setChildrenList(generateNeedResourceList(currentMatchChildResources, thirdLevelResources, new LinkedList<>()));
            }
            resultList.add(target);
        }
        return resultList;
    }

    @Transactional
    public void assignResourcesToRole(Long roleId, List<SysRoleResource> sysRoleResources) {
        // 删除该角色之前的资源
        sysRoleResourceDao.deleteSysRoleResourcesByRoleId(roleId);
        // 重新分配新资源
        sysRoleResourceDao.batchSave(sysRoleResources);
    }

}
